<template>
  <el-form ref="form"
           class="container"
           :="rules"
           :model="registerData">
    <el-form-item class="back">
      <el-icon size="20" style="cursor: pointer" @click="back">
        <el-ArrowLeft/>
      </el-icon>
      <el-text>
        账号登录
      </el-text>
    </el-form-item>
    <el-form-item class="title">
      <el-text>
        欢迎注册喵喵账号
      </el-text>
    </el-form-item>
    <el-form-item class="sub-title">
      <el-text>
        注册账号,开启全新体验
      </el-text>
    </el-form-item>

    <!-- 用户名输入 -->
    <el-form-item class="input"
                  prop="username"
                  :class="{'is-error':userNameHasError, 'is-success': usernameValid}">
      <el-input
        :class="{'error-border':userNameHasError, 'success-border': usernameValid}"
        v-model="registerData.username"
        placeholder="请输入用户名"
        @blur="verUsername"
        :suffix-icon="usernameValid ? 'el-Check' : ''"/>
    </el-form-item>

    <!-- 姓名输入 -->
    <el-form-item class="input"
                  prop="name"
                  :class="{'is-error':nameHasError, 'is-success': nameValid}">
      <el-input
        :class="{'error-border':nameHasError, 'success-border': nameValid}"
        v-model="registerData.name"
        placeholder="请输入姓名"
        @blur="validateName"
        :suffix-icon="nameValid ? 'el-Check' : ''"/>
    </el-form-item>

    <!-- 手机号输入 -->
    <el-form-item class="input"
                  prop="phone"
                  :class="{'is-error':phoneHasError, 'is-success': phoneValid}">
      <el-input
        v-model="registerData.phone"
        type="text"
        placeholder="请输入手机号"
        :class="{'error-border':phoneHasError, 'success-border': phoneValid}"
        @blur="verPhone"
        :suffix-icon="phoneValid ? 'el-Check' : ''"/>
    </el-form-item>

    <!-- 邮箱输入 -->
    <el-form-item class="input"
                  prop="email"
                  :class="{'is-error':emailHasError, 'is-success': emailValid}">
      <el-input
        v-model="registerData.email"
        type="text"
        placeholder="请输入邮箱"
        :class="{'error-border':emailHasError, 'success-border': emailValid}"
        @blur="verEmail"
        :suffix-icon="emailValid ? 'el-Check' : ''"/>
    </el-form-item>

    <!-- 密码输入 -->
    <el-form-item class="input"
                  prop="password"
                  :class="{'is-error':pwHasError, 'is-success': passwordValid}">
      <el-input
        v-model="registerData.password"
        type="password"
        placeholder="输入密码"
        :class="{'error-border':pwHasError, 'success-border': passwordValid}"
        @blur="validatePassword"
        :suffix-icon="passwordValid ? 'el-Check' : ''"
        show-password/>
    </el-form-item>

    <!-- 确认密码 -->
    <el-form-item class="input"
                  prop="rePassword"
                  :class="{'is-error':rePwHasError, 'is-success': rePasswordValid}">
      <el-input
        v-model="registerData.rePassword"
        type="password"
        placeholder="确认输入密码"
        :class="{'error-border':rePwHasError, 'success-border': rePasswordValid}"
        @blur="validateRePassword"
        :suffix-icon="rePasswordValid ? 'el-Ccheck' : ''"
        show-password/>
    </el-form-item>

    <!-- 协议勾选 -->
    <el-form-item class="check">
      <el-checkbox v-model="isChecked"/>
      <el-text>
        同意
      </el-text>
      <el-link type="primary" underline="never">
        《服务条款》
      </el-link>
      <el-link type="primary" underline="never">
        《隐私政策》
      </el-link>
      <el-text>
        和
      </el-text>
      <el-link type="primary" underline="never">
        《儿童隐私政策》
      </el-link>
    </el-form-item>

    <!-- 提交按钮 -->
    <el-form-item class="submit-btn">
      <el-button type="primary" @click.prevent="register" :loading="registerLoading">
        立即注册
      </el-button>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
import {reactive, ref} from "vue";
import {
  ElMessage,
  ElNotification,
  type FormInstance,
  type FormRules
} from "element-plus";

import {doRegister, verifyEmail, verifyPhone, verifyUsername} from "@/api/register";
import type {registerData, registerForm} from "@/api/register/type.ts";


const emit = defineEmits(["change-type"]);
const isChecked = ref(false);
const registerLoading = ref(false);
const form = ref<FormInstance>();

// 表单数据
const registerData = reactive<registerForm>({
  username: "",
  name: "",
  phone: "",
  email: "",
  password: "",
  rePassword: ""
});

// 校验状态
const userNameHasError = ref(false);
const usernameValid = ref(false);
const nameHasError = ref(false);
const nameValid = ref(false);
const phoneHasError = ref(false);
const phoneValid = ref(false);
const emailHasError = ref(false);
const emailValid = ref(false);
const pwHasError = ref(false);
const passwordValid = ref(false);
const rePwHasError = ref(false);
const rePasswordValid = ref(false);

// 校验规则
const rules = reactive<FormRules<registerForm>>({
  username: [
    {required: true, message: "用户名不可为空", trigger: "blur"},
    {min: 6, max: 20, message: "用户名长度为6-20位", trigger: "blur"},
    {
      validator: (_, value, callback) => {
        if (!/^[a-zA-Z0-9_]{6,20}$/.test(value)) {
          callback(new Error("用户名格式错误:仅支持数字、大小写字母和下划线"));
          userNameHasError.value = true;
          usernameValid.value = false;
        } else {
          callback();
          userNameHasError.value = false;
          usernameValid.value = value.length >= 6;
        }
      },
      trigger: "blur"
    },
    {
      validator: async (_, value, callback) => {
        if (!value || value.length < 6) {
          callback();
          return;
        }
        try {
          const res = await verifyUsername(value);
          if (res.data) {
            callback(new Error('用户名已存在'));
            userNameHasError.value = true;
            usernameValid.value = false;
          } else {
            callback();
            userNameHasError.value = false;
            usernameValid.value = true;
          }
        } catch {
          userNameHasError.value = true;
          usernameValid.value = false;
          callback(new Error('校验服务异常'));
        }
      },
      trigger: "blur"
    }
  ],
  name: [
    {required: true, message: "姓名不可为空", trigger: "blur"},
    {min: 3, max: 30, message: "姓名长度为3-30位", trigger: "blur"},
    {
      validator: (_, value, callback) => {
        if (value && value.length >= 3) {
          nameHasError.value = false;
          nameValid.value = true;
        } else {
          nameHasError.value = true;
          nameValid.value = false;
        }
        callback();
      },
      trigger: "blur"
    }
  ],
  phone: [
    {required: true, message: "手机号不可为空", trigger: "blur"},
    {
      validator: (_, value, callback) => {
        if (!/^1[3-9]\d{9}$/.test(value)) {
          callback(new Error("手机号格式错误"));
          phoneHasError.value = true;
          phoneValid.value = false;
        } else {
          callback();
          phoneHasError.value = false;
          phoneValid.value = true;
        }
      },
      trigger: "blur"
    },
    {
      validator: async (_, value, callback) => {
        if (!/^1[3-9]\d{9}$/.test(value)) {
          callback();
          return;
        }
        try {
          const res = await verifyPhone(value);
          if (res.data) {
            callback(new Error('手机号已存在'));
            phoneHasError.value = true;
            phoneValid.value = false;
          } else {
            callback();
            phoneHasError.value = false;
            phoneValid.value = true;
          }
        } catch {
          phoneHasError.value = true;
          phoneValid.value = false;
          callback(new Error('校验服务异常'));
        }
      },
      trigger: "blur"
    }
  ],
  email: [
    {required: true, message: "邮箱不可为空", trigger: "blur"},
    {
      validator: (_, value, callback) => {
        if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
          callback(new Error("邮箱格式错误"));
          emailHasError.value = true;
          emailValid.value = false;
        } else {
          callback();
          emailHasError.value = false;
          emailValid.value = true;
        }
      },
      trigger: "blur"
    }
  ],
  password: [
    {required: true, message: "密码不可为空", trigger: "blur"},
    {min: 6, max: 20, message: "密码长度为6-20位", trigger: "blur"},
    {
      validator: (_, value, callback) => {
        if (!/^[a-zA-Z0-9_]{6,20}$/.test(value)) {
          callback(new Error("密码格式错误"));
          pwHasError.value = true;
          passwordValid.value = false;
        } else {
          callback();
          pwHasError.value = false;
          passwordValid.value = true;
        }
      },
      trigger: "blur"
    }
  ],
  rePassword: [
    {required: true, message: "请确认密码", trigger: "blur"},
    {
      validator: (_, value, callback) => {
        if (registerData.password !== value) {
          callback(new Error("两次密码输入不一致"));
          rePwHasError.value = true;
          rePasswordValid.value = false;
        } else if (value) {
          callback();
          rePwHasError.value = false;
          rePasswordValid.value = true;
        } else {
          callback();
        }
      },
      trigger: "blur"
    }
  ]
});

// 切换到密码登录
function back() {
  emit('change-type', 3);
}

// 校验用户名
async function verUsername() {
  if (!registerData.username || registerData.username.length < 6) return;

  try {
    const res = await verifyUsername(registerData.username);
    if (res.data) {
      userNameHasError.value = true;
      usernameValid.value = false;
      ElMessage.error('用户名已存在');
    } else {
      userNameHasError.value = false;
      usernameValid.value = true;
    }
  } catch {
    userNameHasError.value = true;
    usernameValid.value = false;
    ElMessage.error('校验服务异常');
  }
}

// 校验手机号
async function verPhone() {
  if (!/^1[3-9]\d{9}$/.test(registerData.phone)) return;

  try {
    const res = await verifyPhone(registerData.phone);
    if (res.data) {
      phoneHasError.value = true;
      phoneValid.value = false;
      ElMessage.error('手机号已存在');
    } else {
      phoneHasError.value = false;
      phoneValid.value = true;
    }
  } catch {
    phoneHasError.value = true;
    phoneValid.value = false;
    ElMessage.error('校验服务异常');
  }
}

// 校验邮箱
async function verEmail() {
  if (!registerData.email) return;

  try {
    const res = await verifyEmail(registerData.email);
    if (res.data) {
      emailHasError.value = true;
      emailValid.value = false;
      ElMessage.error('邮箱已存在');
    } else {
      emailHasError.value = false;
      emailValid.value = true;
    }
  } catch {
    emailHasError.value = true;
    emailValid.value = false;
    ElMessage.error('校验服务异常');
  }
}

// 注册提交
async function register() {
  if (!isChecked.value) {
    ElMessage.error('请先阅读并同意相关协议');
    return;
  }

  try {
    registerLoading.value = true;
    const valid = await form.value?.validate();
    if (!valid) return;

    await doRegister({...registerData});

    const notification = ElNotification.success({
      title: "注册成功",
      message: "3秒后将自动跳转到登录页面",
      duration: 3000,
      showClose: true,
      onClick: () => {
        notification.close();
        back();
      }
    });

    setTimeout(() => {
      notification.close();
      back();
    }, 3000);
  } catch (error) {
    console.error('注册失败:', error);
    ElMessage.error('注册失败，请稍后重试');
  } finally {
    registerLoading.value = false;
  }
}

// 辅助校验方法
function validateName() {
  nameValid.value = registerData.name.length >= 3;
  nameHasError.value = !nameValid.value;
}

function validatePassword() {
  passwordValid.value = /^[a-zA-Z0-9_]{6,20}$/.test(registerData.password);
  pwHasError.value = !passwordValid.value;
}

function validateRePassword() {
  rePasswordValid.value = registerData.password === registerData.rePassword && registerData.rePassword.length > 0;
  rePwHasError.value = !rePasswordValid.value;
}
</script>

<style scoped lang="scss">
.container {
  display: flex;
  flex-direction: column;

  .back {
    .el-text {
      position: absolute;
      padding: 6px 8px;
      left: 20px;
      background-color: #4573f6;
      color: #fff;
      font-weight: 400;
      line-height: 20px;
      white-space: nowrap;
      border-radius: 2px;
      opacity: 0;

      &::after {
        content: "";
        position: absolute;
        left: -8px;
        top: 50%;
        transform: translateY(-50%);
        width: 0;
        height: 0;
        border-style: solid;
        border-width: 6px 8px 6px 0;
        border-color: transparent #4573f6 transparent transparent;
      }
    }

    &:hover .el-text {
      opacity: 1;
      transition: opacity 0.3s ease-in-out;
    }
  }

  .title {
    .el-text {
      font-size: 24px;
      --el-text-color: $base-color-text-primary;
      font-weight: bold;
    }
  }

  .sub-title {
    position: relative;
    top: -10px;

    .el-text {
      display: block;
      font-size: 14px;
      color: #9095a2;
      line-height: 22px;
    }
  }

  .input {
    font-size: 16px;
    margin-bottom: 18px;

    .el-input {
      width: 326px;
      height: 46px;
      --el-text-color-placeholder: #585e6d;
      font-size: 16px;
    }

    :deep(.error-border) {
      .el-input__wrapper {
        box-shadow: 0 0 0 1px var(--el-color-danger) inset !important;

        &:hover {
          box-shadow: 0 0 0 1px var(--el-color-danger) inset !important;
        }
      }
    }

    :deep(.success-border) {
      .el-input__wrapper {
        box-shadow: 0 0 0 1px var(--el-color-success) inset !important;

        &:hover {
          box-shadow: 0 0 0 1px var(--el-color-success) inset !important;
        }
      }

      .el-input__suffix {
        color: var(--el-color-success);
      }
    }

    &.is-success {
      :deep(.el-form-item__content) {
        .el-input__validateIcon {
          color: var(--el-color-success);
        }
      }
    }
  }

  .check {
    margin-bottom: 20px;

    :deep(.el-text) {
      --el-text-color: #101010;
    }

    .el-checkbox {
      margin-right: 10px;
    }
  }

  .submit-btn {
    .el-button {
      font-size: 20px;
      width: 352px;
      height: 48px;
      background-color: #3370ff;
    }
  }
}
</style>
